package com.jwj.testback.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.jwj.testback.recordsheet.pojo.DataSourceInfo;
import com.jwj.testback.recordsheet.service.impl.RecordsheetServiceImpl;
import lombok.SneakyThrows;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.jwj.testback.util.IP;


@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.jwj.testback.datasource.dao")
public class DataSourceConfig {


    private DataSource defaultDataSource;

    private Map<String, DataSource> customDataSources = new HashMap<>();

    //默认数据源type
    private static final Object DATASOURCE_TYPE_DEFAULT = "com.alibaba.druid.pool.DruidDataSource";


    //注意：这里需要该注解声明是默认数据源

    /**
     * 注入数据源
     * @return
     */
    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource db1() {
        return DruidDataSourceBuilder.create().build();
    }


    /**
     * 动态数据源配置
     *
     * @return
     */
    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("db1") DataSource db1) {
        MultipleDataSource multipleDataSource = new MultipleDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();

        //创建DataSource并添加到Map
        getDefaultDataSource();

        // 添加更多数据源
        targetDataSources.putAll(customDataSources);
        for (String key : customDataSources.keySet()) {
//            System.out.println("putAll的key："+key);
            MultipleDataSource.dataSourceIds.add(key);
        }

        //添加数据源
        multipleDataSource.setTargetDataSources(targetDataSources);

        //设置默认数据源
        multipleDataSource.setDefaultTargetDataSource(db1);
        return multipleDataSource;
    }


    private Object getDefaultDataSource() {

        Map<String, Map<String, Object>> customInfo = getCustomDataSourceInfo();
        for (String key : customInfo.keySet()) {
            Map<String, Object> dsMap = customInfo.get(key);
            //这里就创建了DataSource
            DataSource ds = buildDataSource(dsMap);

            customDataSources.put(key, ds);

        }
        return DataSourceBuilder.create();
    }


    /**
     * 创建DataSource
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    public DataSource buildDataSource(Map<String, Object> dsMap) {
        try {
            Object type = dsMap.get("type");
            if (type == null)
                type = DATASOURCE_TYPE_DEFAULT;// 默认DataSource

            Class<? extends DataSource> dataSourceType;
            dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);

            String driverClassName = dsMap.get("driver-class-name").toString();
            String url = dsMap.get("url").toString();
            String username = dsMap.get("username").toString();
            String password = dsMap.get("password").toString();

            DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url)
                    .username(username).password(password).type(dataSourceType);
            return factory.build();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @SneakyThrows
    //从默认数据源中读取多数据源
    private Map<String, Map<String, Object>> getCustomDataSourceInfo() {
        Class<? extends DataSource> dataSourceType;
        dataSourceType = (Class<? extends DataSource>) Class.forName("com.alibaba.druid.pool.DruidDataSource");

        DataSourceBuilder factory = DataSourceBuilder.create().driverClassName("com.mysql.cj.jdbc.Driver").url("jdbc:mysql://"+IP.Ip+":3306/test0?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8")
                .username(IP.username).password(IP.password).type(dataSourceType);

        defaultDataSource = factory.build();
        String sql = "select type,`driver_class_name`,url,username,`password`,`dsname` from datasource where status=1";
        JdbcTemplate jdbcTemplate=new JdbcTemplate(defaultDataSource);
        List<DataSourceInfo> infos=jdbcTemplate.query(sql, new RowMapper<DataSourceInfo>() {
            @Override
            public DataSourceInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
                DataSourceInfo info = new DataSourceInfo();
                info.setType(rs.getString("type"));
                info.setDriverClassName(rs.getString("driver_class_name"));
                info.setUrl(rs.getString("url"));
                info.setPassword(rs.getString("password"));
                info.setUsername(rs.getString("username"));
                info.setDsName(rs.getString("dsname"));
                return info;
            }
        });
        Map<String, Map<String, Object>> customMap = new HashMap<>();
        for(DataSourceInfo info:infos) {
            Map<String, Object> dsMap = new HashMap<>();
            dsMap.put("type", info.getType());
            dsMap.put("driver-class-name", info.getDriverClassName());
            dsMap.put("url", info.getUrl());
            dsMap.put("username", info.getUsername());
            dsMap.put("password", info.getPassword());

            customMap.put(info.getDsName(), dsMap);
        }
        return customMap;
    }

    /**
     * 注入session工厂
     * @return
     * @throws Exception
     */
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(multipleDataSource(db1()));

        //添加分页插件
        sqlSessionFactory.setPlugins(new Interceptor[]{paginationInterceptor()});
        return sqlSessionFactory.getObject();
    }

//    /**
//     * 注入事务管理器
//     * @param dataSource dataSource
//     * @return DataSourceTransactionManager
//     */
//    @Bean(name = "baseTransactionManager")
//    public DataSourceTransactionManager buildTransactionManager(@Qualifier("baseDataSource") DataSource dataSource) {
//        return new DataSourceTransactionManager(dataSource);
//    }

    /**
     * 分页插件，自动识别数据库类型
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作， true调回到首页，false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量，默认 500 条，-1 不受限制
        // paginationInterceptor.setLimit(500);
        return paginationInterceptor;
    }

}
